package org.example.queue;

import org.junit.Test;

import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.TimeUnit;

/**
 * ConcurrentLinkedQueue 是由链表结构组成的线程安全的先进先出异步无界队列。
 *
 * @author wangMaoXiong
 * @version 1.0
 * @date 2021/8/5 8:22
 */
public class ConcurrentLinkedQueueTest {

    /**
     * 先进先出
     */
    @Test
    public void testConcurrentLinkedQueue1() {
        ConcurrentLinkedQueue concurrentLinkedQueue = new ConcurrentLinkedQueue();
        for (int i = 1; i < 10; i++) {
            concurrentLinkedQueue.offer(i);
        }
        System.out.println(concurrentLinkedQueue);//[1, 2, 3, 4, 5, 6, 7, 8, 9]

        while (concurrentLinkedQueue.peek() != null) {
            Object poll = concurrentLinkedQueue.poll();
            System.out.println(poll);
        }
    }

    /**
     * 测试 ConcurrentLinkedQueue 得并发线程安全情况
     * 1、假设有 1000 个号(total=1000)，由50个窗口(windows=50)同时卖，每个窗口卖规定卖20个号.
     * 2、最后得结果如果是 ConcurrentLinkedQueue 为空，且各个线程没有卖重复的号，则说明并发正常.
     */
    @Test
    public void testConcurrentLinkedQueue2() {
        ConcurrentLinkedQueue concurrentLinkedQueue = new ConcurrentLinkedQueue();
        int total = 1000;
        int windows = 50;

        for (int i = 1; i <= total; i++) {
            concurrentLinkedQueue.offer(i);
        }

        for (int i = 1; i <= windows; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        for (int i = 0; i < 20; i++) {
                            Object poll = concurrentLinkedQueue.poll();
                            System.out.println(Thread.currentThread().getName() + ":" + poll);
                            Thread.sleep(200);
                        }
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }

        // 主线程主动等待 10 秒,等待子线程执行完毕.
        try {
            TimeUnit.SECONDS.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(concurrentLinkedQueue);//[]
    }


}
